#ifndef DIGITBASE_HPP
#define DIGITBASE_HPP

#include <opencv2/opencv.hpp>
#include <opencv2/text.hpp>
#include <vector>

class DigitBase
{
public:
    static int IsCharacterLinked(cv::Rect charBoundingBox1, cv::Rect charBoundingBox2)
    {

        float widthRatio=((float)charBoundingBox1.width)/((float)charBoundingBox2.width);
        if(widthRatio>2 || widthRatio<0.5)
            return false; //not linked

        float heightRatio=((float)charBoundingBox1.height)/((float)charBoundingBox2.height);
        if(heightRatio>2 || heightRatio<0.5)
            return false;

        cv::Point charCenter1(charBoundingBox1.x+charBoundingBox1.width/2, charBoundingBox1.y+charBoundingBox1.height/2);
        cv::Point charCenter2(charBoundingBox2.x+charBoundingBox2.width/2, charBoundingBox2.y+charBoundingBox2.height/2);

        if(charCenter1.y<charBoundingBox2.y || charCenter1.y>charBoundingBox2.y+charBoundingBox2.height)
            return false;

        if(charCenter2.y<charBoundingBox1.y || charCenter2.y>charBoundingBox1.y+charBoundingBox1.height)
            return false;

        int dx=charCenter2.x-charCenter1.x;

        if(dx>0)
        {
            if(dx>2*charBoundingBox1.width || dx>2*charBoundingBox2.width)
                return false;
            return 1;//linked, char1 first
        }

        if(-dx>2*charBoundingBox1.width || -dx>2*charBoundingBox2.width)
            return false;

        return 2;//linked, char2 first
    }


    static int GetCharIndex(char Character,
                            std::string vocabulary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
            // must have the same order as the clasifier output classes
            )
    {
        size_t index=std::find(vocabulary.begin(),vocabulary.end(),Character)-vocabulary.begin();
        return index;
    }

public:
    cv::Rect boundingBox;
    std::vector<int> out_classes;
    std::vector<double> out_confidences;
    int label;



    DigitBase(cv::Rect boundingBox0)
        : boundingBox(boundingBox0)
    {

    }

    DigitBase(const DigitBase &src)
        : boundingBox(src.boundingBox)
        , out_classes(src.out_classes.begin(), src.out_classes.end())
        , out_confidences(src.out_confidences.begin(), src.out_confidences.end())
        , label(src.label)
    {

    }

    int IsCharacterLinked(const DigitBase &d) const
    {
        return IsCharacterLinked(boundingBox, d.boundingBox);
    }

    void Analysis(const cv::Mat &imageGray, cv::Ptr<cv::text::OCRHMMDecoder::ClassifierCallback> &ocr)
    {
        ocr->eval(imageGray(boundingBox), out_classes, out_confidences);
    }

    void Analysis(const cv::Mat &imageLabel, cv::Ptr<cv::text::OCRHMMDecoder::ClassifierCallback> &ocr, int index)
    {
        cv::Mat labeli;
        cv::compare(imageLabel(boundingBox), index, labeli, cv::CMP_EQ);
        ocr->eval(labeli, out_classes, out_confidences);
    }

    double GetConfidence(int charint) const
    {
        size_t index=std::find(out_classes.begin(),out_classes.end(),charint)-out_classes.begin();
        if(index<out_classes.size())
        {
            return out_confidences[index];
        }
        return 0;
    }

    double GetNumberConfidence(unsigned int num) const
    {
        switch(num)
        {
        case 0:
            return GetConfidence(GetCharIndex('0'))+GetConfidence(GetCharIndex('o'))+GetConfidence(GetCharIndex('O'));
        case 1:
            return GetConfidence(GetCharIndex('1'))+GetConfidence(GetCharIndex('l'))+GetConfidence(GetCharIndex('I'));
        case 2:
            return GetConfidence(GetCharIndex('2'))+GetConfidence(GetCharIndex('z'))+GetConfidence(GetCharIndex('Z'));
        case 3:
            return GetConfidence(GetCharIndex('3'));
        case 4:
            return GetConfidence(GetCharIndex('4'))+GetConfidence(GetCharIndex('A'));
        case 5:
            return GetConfidence(GetCharIndex('5'))+GetConfidence(GetCharIndex('s'))+GetConfidence(GetCharIndex('S'));
        case 6:
            return GetConfidence(GetCharIndex('6'))+GetConfidence(GetCharIndex('b'))+GetConfidence(GetCharIndex('G'));
        case 7:
            return GetConfidence(GetCharIndex('7'));
        case 8:
            return GetConfidence(GetCharIndex('8'))+GetConfidence(GetCharIndex('B'));
        case 9:
            return GetConfidence(GetCharIndex('9'))+GetConfidence(GetCharIndex('g'))+GetConfidence(GetCharIndex('q'));
        default:
            return 0;
        }

    }

};

#endif // DIGITBASE_HPP

